﻿// 
//
#include "headlib.h"
#include "utils.h"
#include "sobel.h"
#include "bilaterafilter.h"
#include "canny.h"
#include "gradient.h"
#include "linedetect.h"

cv::Mat mimg,outmatimg,timg1,timg2,timg3;

char SobelBilateral(matrix inmat, matrix edgemap, matrix outmat, matrix table);
void mainprocess(matrix matimg, matrix mattable, matrix outdata,para cfg, uchar mflag);

int main(int argc, char *argv[])
{
    //ppm2tif();
    //exit(0);
    para cfg;
    matrix inimg,outimg;
    char * imgpath=NULL,*savepath=NULL;
    printf("正在解析参数文件：\n");
    //cfg = parseconfig(argv[1]);               // 读取参数文件
    cfg = parseconfig("./config.txt");          // 读取参数文件
    inimg = readMat(cfg.img);                   // 读取图像
    if (!sizeof(inimg.data)) {
        printf("\"%s\" read failed!\n", imgpath);
    }
    matrix mattable;
    int table[5][5] = { {3,12,24,12,3},
                    {12,48,86,48,12},
                    {24,86,192,86,24},
                    {12,48,86,48,12},
                    {3,12,24,12,3} };   // 高斯算子
    
    mattable.w = 5;
    mattable.h = 5;
    mattable.d = table;
    mattable.channel = 1;

    outimg.h = inimg.h;
    outimg.w = inimg.w;
    outimg.channel = inimg.channel;
    outimg.data = (uchar*)malloc(sizeof(uchar) * outimg.w * outimg.h*outimg.channel);
    mainprocess(inimg, cfg.gaustable, outimg, cfg, GRADIENT_AVG_7X7);
    //mainprocess(inimg, mattable, outimg, cfg, NONMAXDOUBLETHRE);
    writeMat(outimg, cfg.img.savepath, PPM_P6_OUT);
    //free(mattable.d);
    free(cfg.img.inpath);
    free(cfg.img.savepath);
    free(outimg.data);
    free(inimg.data);
    std::cout << "finish!\n";
}

/*
* bilateral filter main process
* parttion module
* 
*/
void mainprocess(matrix matimg, matrix mattable, matrix outdata, para cfg, uchar mflag)
{

    timg1 = cv::Mat::zeros(matimg.h, matimg.w, CV_8UC1);

    matrix tempbuf,outbuf, edgemap;
    edgemap.w = outdata.w;
    edgemap.h = outdata.h;
    edgemap.channel = 1;

    edgemap.data = (uchar*)malloc(edgemap.h * edgemap.w * 1);

    int bandh = matimg.h;
    int bandcnt = matimg.h / bandh + (matimg.h % bandh ? 1 : 0);
    outbuf.w = tempbuf.w = matimg.w;
    outbuf.h = tempbuf.h = bandh;
    outbuf.channel = tempbuf.channel = matimg.channel;

    int r, c, ir = 0, iw = 0, i, j, bufsize = outbuf.h * outbuf.w * outbuf.channel,add,maxindex,bandsize;
    add = 0;
    bandsize = bandh * matimg.w * matimg.channel;
    maxindex = matimg.h * matimg.w * matimg.channel;
    tempbuf.data = (uchar*)malloc(bufsize);
    outbuf.data = (uchar*)malloc(bufsize);
    if (tempbuf.data == NULL || outbuf.data == NULL) {
        printf("<mainprocess>:malloc failied!\n");
        exit(-1);
    }
    for (r = 0; r < outdata.h;) {
        if (add + bufsize >= maxindex) {
            printf("cal end...\n");
            tempbuf.h = outbuf.h = (maxindex - add) / (tempbuf.w * tempbuf.channel);
            bufsize = tempbuf.w * tempbuf.h * tempbuf.channel;
            //memcpy(tempbuf.data, outdata.data + add, tempbuf.w * tempbuf.h * tempbuf.channel);
            //add += tempbuf.w * tempbuf.h * tempbuf.channel;
            //Bilatera(tempbuf, outbuf, mattable);
            //memcpy(outdata.data + add, outbuf.data, outbuf.w * outbuf.h * outbuf.channel);
            ////break;
        }
        //else {
        //    //memcpy(tempbuf.data, outdata.data + add, bandsize);
        //}
        r += tempbuf.h;
        memcpy(tempbuf.data, matimg.data + add, bufsize);

        switch (mflag)
        {
        case SOBELBILATERAL:
            SobelXY(tempbuf, edgemap);
            memcpy(timg1.data, edgemap.data, edgemap.w * edgemap.h * edgemap.channel);
            SobelBilateral(tempbuf,edgemap, outbuf, mattable);
            break;
        case SOBELFILTER:
            SobelFilter(tempbuf, outbuf, mattable);
            break;
        case SOBELFILTER_XY:
            SobelXY(tempbuf, outbuf);
            break;
        case BILATERALFILTER:
            Bilatera(tempbuf, outbuf, mattable);
            break;
        case CANNY:
            mycanny(tempbuf, outbuf, mattable, cfg.cny);

            break;
        case NONMAXDOUBLETHRE:
            NonMaxDoubleThre(tempbuf, outbuf, mattable, cfg.cny);
            break;
        case GRADIENT_9X9:
            gradientprocess(tempbuf, outbuf, mflag);
            break;
        case GRADIENT_7X7:
            gradientprocess(tempbuf, outbuf, mflag);
            break;
        case GRADIENT_3X3:
            gradientprocess(tempbuf, outbuf, mflag);
            break;
        case GRADIENT_AVG_3X3:
            gradientavgprocess(tempbuf, outbuf, mflag);
            break;
        case GRADIENT_AVG_7X7:
            gradientavgprocess(tempbuf, outbuf, mflag);
            break;
        case LINE_DETECT:
            linedetectprocess(tempbuf, outbuf, mattable, mflag);
            break;

        default:
            printf("<mainprocess>please choose one filter!\n");
            exit(-1);
            break;
        }

        memcpy(outdata.data + add, outbuf.data, bufsize);
        add += bandsize;
    }
//    Bilatera(matimg, outdata, mattable);

    printf("mainprocess finish\n");
    //free(outbuf.data);
    //free(tempbuf.data);
    free(edgemap.data);
}


/*
* SobelXY、Bilateral
* mix
* 
*/
char SobelBilateral(matrix inmat, matrix edgemap, matrix outmat, matrix table) {
    matrix tablex, tabley;
    int r, c, i, j, chan, index,t2;
    int arrlv[4];
    float ws[5] = { 1,0.3,0.2,0,0 };

    int t,sum,w,out,ctr;   
    if (inmat.channel != 1) {
        printf("<SobelBilateral>warning:\tinput mulity channel image!\n");
    }
    for (r = 0; r < inmat.h; r++) {
        for (c = 0; c < inmat.w; c++) {
            for (chan = 0; chan < inmat.channel; chan++) {
                if (c <= 2 || c >= edgemap.w - 2 || r <= 2 || r >= edgemap.h - 2) {
                    outmat.data[(r * outmat.w + c) * outmat.channel + chan] = inmat.data[((r)*outmat.w + c) * outmat.channel + chan];
                    continue;
                }
                ctr = int(edgemap.data[r * outmat.w + c]/63);
                ctr = clip(ctr, 0, 4);
                sum = 0;
                out = 0;
                if (r == 117&& c == 416) {
                    out = 0;
                }
                for (i = 0; i < table.h; i++) {
                    for (j = 0; j < table.w; j++) {            
                        
                        index = (r + i - (table.h >> 1)) * edgemap.w + c + j - (table.w >> 1);
                        t2 = t = (int)(edgemap.data[index]/63);
                        t2 = abs(ctr - t);
                        w = (int)(((double)((int*)table.d)[i * table.w + j]) * ws[t2]);
                        sum += w;
                        out += w* inmat.data[index + chan];
                       //printf("t:%d %dx%d=%d\t",t, w, inmat.data[index + chan],
                       //     inmat.data[index + chan] * w);
                    }
                    //printf("\n");
                }
                //printf("sum:%d\n", sum);
                //printf("\n");
                if (sum == 0) {
                    printf("ctr:%d,sum:%d\n", ctr, sum);
                }
                out = sum == 0 ? out : out / sum;
                outmat.data[(r * outmat.w + c) * outmat.channel + chan] = (uchar)(out);
            }
        }
    }
    printf("SobelBilateral finish!\n");
    return OK;
}


